package com.dream.auth.config;

import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextRepository;

import com.dream.auth.security.CustomPasswordEncoder;
import com.dream.auth.security.JwtAuthenticationFilter;
import com.dream.auth.security.LoginSuccessHandler;
import com.dream.auth.security.UserDetailsServiceImpl;

import lombok.RequiredArgsConstructor;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

	private final JwtAuthenticationFilter jwtAuthenticationFilter;

	private final UserDetailsServiceImpl userDetailsService;

	private final SecurityContextRepository securityContextRepository;

	private final LoginSuccessHandler loginSuccessHandler;

	private final CustomPasswordEncoder customPasswordEncoder;

	private static final String[] WHITELIST = {
			// 静态资源
			"/css/**", "/js/**", "/images/**", "/fonts/**", "/favicon.ico", "/assets/**",
			// Swagger/Knife4j
			"/swagger-ui.html", "/webjars/**", "/swagger-resources/**", "/v3/api-docs/**",
			// OAuth2相关
			"/oauth2/**", "/.well-known/openid-configuration", "/.well-known/jwks.json",
			// 认证相关
			"/login", "/auth/login", "/auth/refresh-token",
			// 错误页面
			"/error",

			"/test/**" };

	@Bean
	@Order(2)
	SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
		http.authorizeHttpRequests(authorize -> authorize.requestMatchers(WHITELIST)
				.permitAll()
				.requestMatchers("/index")
				.authenticated()
				// 确保OAuth2端点可访问
				// .requestMatchers("/oauth2/**")
				// .permitAll()
				.anyRequest()
				.authenticated())
				.csrf(csrf -> csrf.disable())
				.cors(Customizer.withDefaults())
				.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
				.securityContext(context -> context.securityContextRepository(securityContextRepository))
				.formLogin(form -> form.loginPage("/login")
						.loginProcessingUrl("/login")
						.successHandler(loginSuccessHandler)
						.failureHandler((request, response, exception) -> {
							response.setContentType("application/json;charset=UTF-8");
							response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
							response.getWriter().write("{\"message\":\"用户名或密码错误\"}");
						}))
				// .exceptionHandling(
				// exceptions -> exceptions.authenticationEntryPoint((request, response,
				// authException) -> {
				// if (isAjaxRequest(request)) {
				// response.setContentType("application/json;charset=UTF-8");
				// response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
				// response.getWriter().write("{\"message\":\"请先登录\"}");
				// } else {
				// response.sendRedirect("/login");
				// }
				// }))
				.authenticationProvider(authenticationProvider())
				.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

		return http.build();
	}

	@Bean
	public WebSecurityCustomizer webSecurityCustomizer() {
		return web -> web.ignoring()
				.requestMatchers(
						// 静态资源
						"/css/**", "/js/**", "/images/**", "/fonts/**", "/favicon.ico",
						// Swagger/Knife4j
						"/doc.html", "/webjars/**", "/swagger-resources", "/swagger-resources/**", "/doc.html",
						"/v2/api-docs", "/v2/api-docs/**",
						// Actuator端点
						"/actuator/**",
						// 其他
						"/error");
	}

	@Bean
	public AuthenticationProvider authenticationProvider() {
		DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
		authProvider.setUserDetailsService(userDetailsService);
		authProvider.setPasswordEncoder(customPasswordEncoder);
		return authProvider;
	}

	@Bean
	public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
		return config.getAuthenticationManager();
	}
}